#!/usr/bin/Python
# coding=utf-8
import os
import signal
import sys
import getopt
import pytoml

from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
from thrift.transport import TSocket, TTransport

sys.path.append('..')
from i_util.thread_pool import ThreadPool
from i_util.input_thread import InputThread
from i_util.heart_beat import HeartbeatThread
from bdp.i_crawler.i_entity_extractor import EntityExtractorService
from bdp.i_crawler.i_entity_extractor.ttypes import ResultResp, EntityResp
import traceback
import json
from i_util.ProfilingUtil import profiler_creator
from i_util.ProfilingUtil import profiling_signal_handler


class EntityExtractorServer(object):
    def __init__(self, conf):
        self.conf = conf
        self.log = common.log
        thread_locals = {'processor': (EntityExtractorProccessor, (conf,)), 'profiler': (profiler_creator, ())}
        self.process_pool = ThreadPool(conf['server']['process_thread_num'], thread_locals)
        self.input_thread = InputThread(conf['beanstalk_conf'], conf['log'], self.process_pool)
        self.heart_beat_thread = HeartbeatThread("entity_extractor", conf)

    def start(self):
        self.input_thread.start()
        self.heart_beat_thread.start()
        self.log.info("start EntityExtractorServer!")
    def stop(self,message):
        self.input_thread.stop()
        self.log.info("stop ExtractorServer %s!" % (message))


class EntityExtractorHandler(object):
    def __init__(self, conf):
        self.conf = conf
        self.log = common.log

    def reload(self, topic_id=-1):
        '''重新加载topic schema和解析器'''
        data = {}
        try:
            self.log.info("start reload topic_id[%s]" % topic_id)
            data = entity_route_obj.reload(topic_id)
            self.log.info("finish reload topic_id[%s]" % topic_id)
            msg  = "finish reload topic_id[%s]" % topic_id
        except:
            self.log.error("reload fail reason[%s]" % traceback.format_exc())
            msg = "reload fail reason[%s]" % traceback.format_exc()

        resp = ResultResp(code=1, msg=msg, data=json.dumps(data))
        return resp

    def add_topic(self, topic_info):
        '''添加topic schema'''
        try:
            topic_info = json.loads(topic_info)
            self.log.info("start_add_topic, topic_info[%s]" % topic_info)
            result = entity_route_obj.add_topic(topic_info)
            self.log.info("finish_add_topic, ret[%s]\ttopic_info[%s]" % (result.get('MSG',''), topic_info))
        except:
            self.log.error("add_topic_fail, ret:%s" % traceback.format_exc())

        resp = ResultResp(code=result.get('COSD',10000), msg=result.get('MSG',''), data='')
        return resp

    def add_extractor(self, extractor_info):
        '''添加解析器'''
        try:
            extractor_info = json.loads(extractor_info)
            self.log.info("start_add_extractor, extractor_info[%s]" % extractor_info)
            result = entity_route_obj.insert_extractor(extractor_info)
            self.log.info("finish_add_extractor, ret[%s]\textractor_info[%s]" % (result.get('MSG',''), extractor_info))

            resp = ResultResp(code=result.get('COSD',10000), msg=result.get('MSG',''), data='')
        except:
            self.log.error("add_extractor_fail, ret:%s"%traceback.format_exc())
        return resp

    def entity_extract(self, parse_info):
        '''实体解析数据'''
        try:
            extract_obj = EntityExtractor(self.conf)
            ret = extract_obj.entity_extractor(parse_info)
            entity_extract_data_list = ret.get('LIST', [])
        except:
            self.log.error("entity_extract_fail, ret:%s" % traceback.format_exc())

        resp = EntityResp(code=ret.get('CODE', -10000), msg=ret.get('MSG', ''),
                          entity_data_list=entity_extract_data_list)
        return resp

def main(conf):
    signal.signal(signal.SIGTERM, signal.SIG_DFL)
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    signal.signal(signal.SIGUSR1, lambda a, b: profiling_signal_handler("entity_extractor", a, b))

    extract_server = EntityExtractorServer(conf)
    extract_server.start()

    try:
        handler   = EntityExtractorHandler(conf)
        processor = EntityExtractorService.Processor(handler)
        transport = TSocket.TServerSocket(port=conf['server']['port'])
        tfactory  = TTransport.TBufferedTransportFactory()
        pfactory  = TBinaryProtocol.TBinaryProtocolFactory()
        server    = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)
        server.setNumThreads(conf['server']['server_thread_num'])
        server.serve()
    except Exception, e:
        common.log.error(str(e))
        extract_server.stop("fail")
        os._exit(1)
    extract_server.stop("success")


def usaget():
    pass

if __name__ == '__main__':
    from conf import get_config
    try:
        file_path = './entity.toml'
        opt, args = getopt.getopt(sys.argv[1:], 'f:', ['help'])
        for name, value in opt:
            if name == "-f":
                file_path = value
            elif name in ("-h", "--help"):
                usaget()
                sys.exit()
            else:
                assert False, "unhandled option"
        with open(file_path, 'rb') as config:
            config = pytoml.load(config)
        conf = get_config(config)
        import common

        from entity_extractor_proccessor import EntityExtractorProccessor
        from entity_extractor import EntityExtractor
        from entity_extractor_route import entity_route_obj

        config['log'] = common.log
        main(config)

    except:
        print traceback.format_exc()
